<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace app\manage\controller\admin;

use app\common\model\MemberMiniappOrder;
use app\manage\model\AuthGroup;
use buwang\base\AdminBaseController;
use buwang\util\Caches;
use think\facade\View;
use app\manage\model\admin\MiniappModule as MiniappModuleModel;
use think\Response;


/**
 * @ControllerAnnotation(title="应用功能表")
 */
class MiniappModule extends AdminBaseController
{
    use \buwang\traits\Crud;

    public function initialize()
    {
        parent::initialize();
        $this->layout && $this->app->view->engine()->layout($this->layout);
        $this->model = new \app\manage\model\admin\MiniappModule();
        $this->assign('getTypeList', $this->model->getTypeList());
    }

    /**
     * @NodeAnotation(title="列表")
     */
    public function index()
    {
        $miniapp_id = request()->param('miniapp_id/d', 0);
        if ($this->request->isAjax()) {
            if (input('selectFieds')) {
                return $this->selectList();
            }
            list($page, $limit, $where) = $this->buildTableParames();
            $module_miniapp_id = Caches::get('module_miniapp_id');
            //兼容API接口
            if($miniapp_id) $module_miniapp_id=$miniapp_id;

            !$module_miniapp_id && $module_miniapp_id = 0;
            $where[] = ['miniapp_id', '=', $module_miniapp_id];
            $count = $this->model
                ->where($where)
                ->count();
            $list = $this->model
                ->where($where)
                ->page($page, $limit)
                ->order($this->sort)
                ->select();
            $data = [
                'total' => $count,
                'list' => $list,
            ];
            return $this->success('success', $data);
        }else{
            Caches::set('module_miniapp_id', $miniapp_id);
            return view();
        }
    }

    /**
     * @NodeAnotation(title="添加")
     */
    public function add()
    {
        if ($this->request->isAjax()) {
            $post = $this->request->post();
            $rule = [
                'miniapp_id|miniapp_id参数' => 'require',
                'name|套餐名' => 'require',
                'price_json|套餐规格' => 'require',
                'group_id|套餐组标识' => 'require',
                'group_name|套餐组标识' => 'require',
                'desc|套餐描述' => 'require',
            ];
            $this->validate($post, $rule);
            //判断是否存在模块节点重复
            if(!AuthGroup::checkGroupNodes(explode(',',$post['group_id']))) return $this->error(AuthGroup::getError());

            $count = $this->model->where(['miniapp_id'=>$post['miniapp_id'],'group_id'=>$post['group_id']])->count();
            if($count >=1) return $this->error('已经存在相同套餐，请勿重复添加！');
            try {
                //if(is_array($post['price_json'])) $post['price_json']=json_encode($post['price_json']);
                if (is_array($post['price_json'])) {
                    $post['price_json'] = json_encode(
                        $this->_packPriceJson($post['price_json']),
                        JSON_UNESCAPED_UNICODE
                    );
                }
                $save = $this->model->allowField(['id', 'miniapp_id', 'group_id', 'price_json','name','type','price','valid_days','desc','sort','status','group_name'])->save($post);
            } catch (\Exception $e) {
                return $this->error('保存失败:' . $e->getMessage());
            }
            if ($save) return $this->success('保存成功');
            else return $this->error('保存失败');
        }
        //附加应用ID
        $miniapp_id = Caches::get('module_miniapp_id');
        !$miniapp_id && $miniapp_id = 0;
        View::assign('miniapp_id', $miniapp_id);
        return view();
    }


    /**
     * @NodeAnotation(title="编辑")
     */
    public function edit($id)
    {
        if(!intval($id)) return $this->error('id参数缺失');
        $row = $this->model->find($id);
        if ($row->isEmpty()) return $this->error('数据不存在');
        if ($this->request->isAjax()) {
            $post = $this->request->post();
            $rule = [
                'id|id参数' => 'require',
                'miniapp_id|miniapp_id参数' => 'require',
                'name|套餐名' => 'require',
                'group_id|套餐组标识' => 'require',
                'group_name|套餐组标识' => 'require',//新版本扩展字段，比group_id更通用
                'price_json|套餐规格' => 'require',
                'desc|套餐描述' => 'require',
            ];
            $this->validate($post, $rule);
            //判断是否存在模块节点重复
            if(!AuthGroup::checkGroupNodes(explode(',',$post['group_id']))) return $this->error(AuthGroup::getError());
            try {
                //if(is_array($post['price_json'])) $post['price_json']=json_encode($post['price_json']);
                if (is_array($post['price_json'])) {
                    $post['price_json'] = $this->_getUpdatePriceJson(
                        $row['price_json'],
                        $post['price_json'],
                        $row['id']
                    );
                    $post['price_json'] = json_encode($post['price_json']);
                }
                $save = $row->allowField(['id', 'miniapp_id', 'group_id', 'price_json','name','type','price','valid_days','desc','sort','status','group_name'])->save($post);
            } catch (\Exception $e) {
                return $this->error('编辑失败');
            }
            if ($save) return $this->success('编辑成功');
            else return $this->error('编辑失败');
        }
        View::assign('row', $row);
        return view();
    }





    /**
     * 角色组
     */
    public function group(){
        $miniapp_id = $this->request->get('miniapp_id/d', 0);
        $id = $this->request->get('id/d', 0);//这个
        //得到當前角色組
        $data = MiniappModuleModel::getAppRoles($miniapp_id,$id,0,[]);
        return $this->success('ok', $data);
    }

    /**
     * 获取应用的基础套餐
     * @return \think\Response
     */
    public function meal(){
        $miniapp_id = $this->request->get('miniapp_id/d', 0);
        $id = $this->request->get('id/d', 0);//这个
        //得到當前角色組
        $data = MiniappModuleModel::getAppRolesApi($miniapp_id,$id);
        return $this->success('ok', $data);
    }

    /**
     * 获取套餐规格扩展字段.
     *
     * @return \think\Response
     */
    public function packageExtendedFields():Response {
        $miniapp_id = $this->request->get('miniapp_id/d', 0);
        if (empty($miniapp_id)) {
            return $this->success('ok', ['packageExtendedFields' => []]);
        }

        return $this->success('ok', [
            'packageExtendedFields' => MiniappModuleModel::getAppMealSpecExtendFieldApi($miniapp_id),
        ]);
    }

    protected function _packPriceJson(array $priceJson):array {
        $pack = [];
        // 给每个套餐规格增加唯一id.
        foreach ($priceJson as $item) {
            $item['uuid'] = uniqid();
            $pack[]       = $item;
        }

        return $pack;
    }

    /**
     * 规格化套餐规格的更新操作.
     *
     * @param string $old
     * @param array  $new
     * @param int    $id
     *
     * @return array
     * @throws \think\db\exception\DbException
     */
    protected function _getUpdatePriceJson(string $old, array $new, int $id):array {
        if (empty($old)) {
            return $new;
        }

        // 给每个套餐规格增加唯一id.
        $assNew = [];
        foreach ($new as $itemNew) {
            if (!isset($itemNew['uuid'])) {
                $itemNew['uuid'] = uniqid();
            }

            $assNew[ $itemNew['uuid'] ] = $itemNew;
        }

        $oldParsed = json_decode($old, TRUE);
        if (!is_array($oldParsed)) {
            return $new;// 直接覆盖正确的.
        }

        $assOld = [];
        foreach ($oldParsed as $item1) {
            if (!isset($item1['uuid'])) {
                $item1['uuid'] = uniqid();// 补充uuid.
            }

            $assOld[ $item1['uuid'] ] = $item1;
        }

        $result  = [];
        $removed = [];// 被移除的.
        foreach ($assOld as $uuid => $item2) {
            if (!isset($assNew[ $uuid ])) {
                $removed[ $uuid ] = $item2;
                continue;
            }

            $result[ $uuid ] = $assNew[ $uuid ];// 覆盖修改.
            unset($assNew[ $uuid ]);
        }

        // 检测被移除的已经有购买的情况.
        foreach ($removed as $uuid => $itemRm) {
            if (MemberMiniappOrder::where('miniapp_module_id', $id)
                    ->where('miniapp_module_price_id', $uuid)
                    ->count() > 0) {
                $this->error(sprintf('套餐规格%s被占用中，无法删除', $itemRm['title'] ?? 'N/A'));
            }
        }

        // 剩下是新增的.
        foreach ($assNew as $uuid => $item3) {
            $result[ $uuid ] = $item3;
        }

        return array_values($result);
    }
}